<?php
/**
 * Password Class
 * 
 * This class provides methods to generate new password hashes and authenticate
 * against existing ones.
 * 
 * Inspired by http://www.bigroom.co.uk/blog/php-password-security
 *
 */

class Password {

	/**
	 * Generate a hash of the supplied text
	 *
	 * @param   string $text       the plain text password to be hashed
	 * @param   string $salt       the salt to use if specified
	 * @param   string $algorithm  the algorithm to use if specified
	 * @return  string
	 * @author  Colin Burn-Murdoch
	 **/
	static public function hash($text, $algorithm='whirlpool', $salt=false) {
		if ($salt === false) $salt = self::salt(64);
		Password::valid_algorithm($algorithm);
		return $algorithm . ':' . $salt . ':' . hash($algorithm, $salt . $text);
	}
	
	/**
	 * Check a text password against a hash
	 *
	 * @param   string $text       plain text password
	 * @param   string $hash       hashed password to check against
	 * @return  boolean
	 * @author  Colin Burn-Murdoch
	 **/
	static public function auth($text, $hash) {
		list($algorithm, $salt, $encrypted) = explode(":", $hash);
		Password::valid_algorithm($algorithm);
		return $hash == Password::hash($text, $algorithm, $salt);
	}
	
	/**
	 * Generate a random hexadecimal salt to use in new passwords.
	 *
	 * @param   integer            length of required salt
	 * @return  string
	 * @author  Colin Burn-Murdoch
	 **/
	static private function salt($len=null) {
		!is_null($len) or $len = 64;
		$salt = '';
		for($i=0;$i<$len;$i++) {
			$salt .= dechex(mt_rand(0, 15));
		}
		return $salt;
	}
	
	static private function valid_algorithm($algorithm) {
		if (!in_array($algorithm, hash_algos())) {
			throw new Exception($algorithm . ' is not a valid algorithm on this system.');
		}
	}
}
